﻿
using System;
using System.Collections.ObjectModel;
using EasyTest.Logger;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.IE;
using OpenQA.Selenium.Interactions;

namespace EasyTest {

    /// <summary>
    /// 
    /// </summary>
    public class Action {

        /// <summary>
        /// Run valid javascript passed to method.
        /// </summary>
        /// <param name="javascript">javascript to run.</param>
        public static void ExecuteJavaScript(string javascript) {

            EasyTestLogger.Log(string.Format("javascript = {0}", javascript));

            IJavaScriptExecutor js = Browser.Driver as IJavaScriptExecutor;
            js.ExecuteScript(javascript);
        }

        /// <summary>
        /// Get Selenium By object that can be used to find specific document elements.
        /// </summary>
        /// <param name="findBy">HTML text to identify and find elements within a document.</param>
        /// <returns>Selenium By object</returns>
        public static By GetFindBy(string findBy) {

            //EasyTestLogger.Log(string.Format("findBy = {0}", findBy));

            if (findBy.Contains("<") & findBy.Contains(">")) {
                return By.TagName(findBy.Trim('<').Trim('>'));
            }
            if (findBy.Contains("~")) {
                return By.Name(findBy.TrimStart('~'));
            }
            if (findBy.Contains("//")) {
                return By.XPath(findBy);
            }
            if ((findBy.Contains(".") | findBy.Contains("#") | findBy.Contains("[")) & (!findBy.Contains(".."))) {
                return By.CssSelector(findBy);
            } else {
                return By.Id(findBy);
            }
        }

        /// <summary>
        /// Execute the Click() method on the object identified in the findBy parameter.
        /// </summary>
        /// <param name="findBy">HTML text to identify and find elements within a document.</param>
        public static void Click(string findBy) {
            Click(GetFindBy(findBy));
        }

        /// <summary>
        /// Execute the Click() method on the object identified in the findBy parameter.
        /// </summary>
        /// <param name="findBy">Selenium object that provides a mechanism to find elements within a document</param>
        public static void Click(By findBy) {

            EasyTestLogger.Log(string.Format("findBy = {0}", findBy));
            WaitFor(findBy, 20);
            if (Browser.Driver is InternetExplorerDriver)
            {
                Browser.Driver.SwitchTo().ActiveElement();            
            }
                Browser.Driver.FindElement(findBy).Click();

        }

        /// <summary>
        /// Execute the DoubleClick() method on the object identified in the findBy parameter.
        /// </summary>
        /// <param name="findBy">HTML text to identify and find elements within a document.</param>
        public static void DoubleClick(string findBy) {
            DoubleClick(GetFindBy(findBy));
        }

        /// <summary>
        /// Execute the DoubleClick() method on the object identified in the findBy parameter.
        /// </summary>
        /// <param name="findBy">Selenium object that provides a mechanism to find elements within a document</param>
        public static void DoubleClick(By findBy) {

            EasyTestLogger.Log(string.Format("findBy = {0}", findBy));
            WaitFor(findBy, 20);
            if (Browser.Driver is InternetExplorerDriver)
            {
                Browser.Driver.SwitchTo().ActiveElement();
            }
            
            Actions action = new Actions(Browser.Driver);
            action.DoubleClick(Browser.Driver.FindElement(findBy));
            action.Perform();
        }
        public static int Count(string findBy)
        {
            return Browser.Driver.FindElements(GetFindBy(findBy)).Count;
        }
        /// <summary>
        /// Add text to the document element found by the findBy parameter.
        /// </summary>
        /// <param name="findBy">HTML text to identify and find elements within a document.</param>
        /// <param name="text">Text string to set in the object found</param>
        public static void Set(string findBy, string text) {
            Set(GetFindBy(findBy), text);
        }

        /// <summary>
        /// Add text to the document element found by the findBy parameter.
        /// </summary>
        /// <param name="findBy">Selenium object that provides a mechanism to find elements within a document</param>
        /// <param name="text">Text string to set in the object found</param>
        public static void Set(By findBy, string text) {

            EasyTestLogger.Log(string.Format("findBy = {0}, text = {1}", findBy, text));

            Browser.Driver.FindElement(findBy).SendKeys(text);
            //Tab after to offset focus
            Browser.Driver.FindElement(findBy).SendKeys(Keys.Tab);
        }

        /// <summary>
        /// Call the Clear() method on the document element found by the findBy parameter.
        /// </summary>
        /// <param name="findBy">HTML text to identify and find elements within a document.</param>
        public static void Clear(string findBy) {
            Clear(GetFindBy(findBy));
        }

        /// <summary>
        /// Call the Clear() method on the document element found by the findBy parameter.
        /// </summary>
        /// <param name="findBy">Selenium object that provides a mechanism to find elements within a document</param>
        private static void Clear(By findBy) {
            WaitFor(findBy);
            EasyTestLogger.Log(string.Format("findBy = {0}", findBy));

            Browser.Driver.FindElement(findBy).Clear();
        }

        /// <summary>
        /// Get the text string of the document element found by the findBy parameter.
        /// </summary>
        /// <param name="findByText">String representing the Document Element to search for.</param>
        /// <returns>Text string in the Text property.</returns>
        public static string GetText(string findByText) {
            return GetText(GetFindBy(findByText));
        }

        /// <summary>
        /// Get the text string of the document element found by the findBy parameter.
        /// </summary>
        /// <param name="findBy">Selenium object that provides a mechanism to find elements within a document</param>
        /// <returns>Text string in the Text property.</returns>
        private static string GetText(By findBy) {

            EasyTestLogger.Log(string.Format("findBy = {0}", findBy));
            return Browser.Driver.FindElement(findBy).Text;
        }

        /// <summary>
        /// Get the Value attribute of the document element found by the findBy parameter.
        /// </summary>
        /// <param name="findBy">HTML text to identify and find elements within a document.</param>
        /// <returns>String representing the Value attribute.</returns>
        public static string GetValue(string findBy) {
            return GetValue(GetFindBy(findBy));
        }

        /// <summary>
        /// Get the Value attribute of the document element found by the findBy parameter.
        /// </summary>
        /// <param name="findBy">Selenium object that provides a mechanism to find elements within a document</param>
        /// <returns>String representing the Value attribute.</returns>
        private static string GetValue(By findBy) {

            EasyTestLogger.Log(string.Format("findBy = {0}", findBy));

            return Browser.Driver.FindElement(findBy).GetAttribute("value");
        }

        /// <summary>
        /// Return whether or not the .Selected property of the document element found by the findBy parameter is set.
        /// </summary>
        /// <param name="findBy">HTML text to identify and find elements within a document.</param>
        /// <returns>True/False representing whether or not the .Selected property is set.</returns>
        public static bool IsSelected(string findBy) {
            return IsSelected(GetFindBy(findBy));
        }

        /// <summary>
        /// Return whether or not the .Selected property of the document element found by the findBy parameter is set.
        /// </summary>
        /// <param name="findBy">Selenium object that provides a mechanism to find elements within a document</param>
        /// <returns>True/False representing whether or not the .Selected property is set.</returns>
        public static bool IsSelected(By findBy) {

            EasyTestLogger.Log(string.Format("findBy = {0}", findBy));

            return Browser.Driver.FindElement(findBy).Selected;
        }

        /// <summary>
        /// Return whether or not the disabled attribute of the document element found by the findBy parameter is set.
        /// </summary>
        /// <param name="findBy">HTML text to identify and find elements within a document.</param>
        /// <returns>True/False representing whether or not the disbled attribute is set.</returns>
        public static bool IsDisabled(string findBy) {
            return IsDisabled(GetFindBy(findBy));
        }

        /// <summary>
        /// Return whether or not the disabled attribute of the document element found by the findBy parameter is set.
        /// </summary>
        /// <param name="findBy">Selenium object that provides a mechanism to find elements within a document</param>
        /// <returns>True/False representing whether or not the disbled attribute is set.</returns>
        public static bool IsDisabled(By findBy) {

            EasyTestLogger.Log(string.Format("findBy = {0}", findBy));

            return CheckForAttribute(findBy, "disabled", "true");
        }
        public static bool IsReadOnly(string findBy)
        {
            EasyTestLogger.Log(string.Format("findBy = {0}", findBy));
            return CheckForAttribute(GetFindBy(findBy), "readOnly", "readonly");
        }

        /// <summary>
        /// Returns whether or not the attribute value matches the expected value for the attribute name passed for the document element found by the findBy parameter.
        /// </summary>
        /// <param name="findBy">HTML text to identify and find elements within a document.</param>
        /// <param name="attribute">Name of the attribute to check.</param>
        /// <param name="attributeExpectedValue">Expected value to check for.</param>
        /// <returns>True/False representing whether or not the expected attribute value matches the actual value for the attribute passed.</returns>
        public static bool CheckForAttribute(string findBy, string attribute, string attributeExpectedValue) {
            return CheckForAttribute(GetFindBy(findBy), attribute, attributeExpectedValue);
        }

        /// <summary>
        /// Returns whether or not the attribute value matches the expected value for the attribute name passed for the document element found by the findBy parameter.
        /// </summary>
        /// <param name="findBy">Selenium object that provides a mechanism to find elements within a document</param>
        /// <param name="attribute">Name of the attribute to check.</param>
        /// <param name="attributeExpectedValue">Expected value to check for.</param>
        /// <returns>True/False representing whether or not the expected attribute value matches the actual value for the attribute passed.</returns>
        public static bool CheckForAttribute(By findBy, string attribute, string attributeExpectedValue) {

            EasyTestLogger.Log(string.Format("findBy = {0} attribute = {1} attributeExpectedValue {2}", findBy, attribute, attributeExpectedValue));

            try {
                string attributeActualValue = GetAttributeValue(findBy, attribute);
                if (attributeActualValue == attributeExpectedValue) {
                    return true;
                }
            } catch (Exception e) {
                return false;
            }
            return false;
        }

        /// <summary>
        /// Returns the attribute for the attribute name passed for the document element found by the findBy parameter.
        /// </summary>
        /// <param name="findBy">HTML text to identify and find elements within a document.</param>
        /// <param name="attribute">Name of the attribute to check.</param>
        /// <returns>String representing the attribute.</returns>
        public static string GetAttributeValue(string findBy, string attribute) {
            return GetAttributeValue(GetFindBy(findBy), attribute);
        }

        /// <summary>
        /// Returns the attribute for the attribute name passed for the document element found by the findBy parameter.
        /// </summary>
        /// <param name="findBy">Selenium object that provides a mechanism to find elements within a document</param>
        /// <param name="attribute">Name of the attribute to check.</param>
        /// <returns>String representing the attribute.</returns>
        public static string GetAttributeValue(By findBy, string attribute) {

            EasyTestLogger.Log(string.Format("findBy = {0} attribute = {1}", findBy, attribute));

            return Browser.Driver.FindElement(findBy).GetAttribute(attribute);
        }

        /// <summary>
        /// Returns the style attribute for the document element found by the findBy parameter.
        /// </summary>
        /// <param name="findBy">Selenium object that provides a mechanism to find elements within a document</param>
        /// <returns>Text contained in the style attribute.</returns>
        public static string GetStyle(By findBy) {

            EasyTestLogger.Log(string.Format("findBy = {0}", findBy));

            return Browser.Driver.FindElement(findBy).GetAttribute("style");
        }

        /// <summary>
        /// Object used to validate properties of a document element or its attribute(s).
        /// </summary>
        public static class Verify {
            /// <summary>
            /// Verify that element is Enabled
            /// </summary>
            /// <param name="findBy">The string reprensenting the element</param>
            public static void Enabled(string findBy)
            {
                Assert.IsTrue(Browser.Driver.FindElement(GetFindBy(findBy)).Enabled);
            }
            /// <summary>
            /// Verify the element is Disabled
            /// </summary>
            /// <param name="findBy">The string representing the element</param>
            public static void Disabled(string findBy)
            {
                Assert.IsFalse(Browser.Driver.FindElement(GetFindBy(findBy)).Enabled);
            }
            public static void Readonly(string findBy)
            {
                bool readOnly = false;
                try
                {
                    readOnly = Convert.ToBoolean(Browser.Driver.FindElement(GetFindBy(findBy)).GetAttribute("readOnly"));
                }
                catch{}
                Assert.IsTrue(readOnly);
                
            }
            /// <summary>
            /// Check the Text property of the document element found by the findBy parameter.
            /// </summary>
            /// <param name="findBy">HTML text to identify and find elements within a document.</param>
            /// <param name="textToVerify">Text to check for.</param>
            /// <param name="focus">Document container with controls to search for.</param>
            public static void Text(string findBy, string textToVerify, Focus focus) {
                Text(findBy, textToVerify, focus, "");
            }

            /// <summary>
            /// Process this Verify by a Text comparison.
            /// </summary>
            /// <param name="findBy">HTML text to identify and find elements within a document.</param>
            /// <param name="textToVerify">Text to compare with the .Text property of the Document Element found.</param>
            /// <param name="focus">Document container with controls to search for.</param>
            /// <param name="errorMessage">Error message to be displayed if there is no match.</param>
            public static void Text(string findBy, string textToVerify, Focus focus, string errorMessage) {
                Text(GetFindBy(findBy), textToVerify, focus, errorMessage);
            }

            /// <summary>
            /// Process this Verify by a Text comparison.
            /// </summary>
            /// <param name="findBy">Selenium object that provides a mechanism to find elements within a document</param>
            /// <param name="textToVerify">Text to compare with the .Text property of the Document Element found.</param>
            /// <param name="focus">Document container with controls to search for.</param>
            /// <param name="errorMessage">Error message to be displayed if there is no match.</param>
            public static void Text(By findBy, string textToVerify, Focus focus, string errorMessage) {

                EasyTestLogger.Log(string.Format("findBy = {0} textToVeriy = {1} focus = {2} errorMessage = {3}", findBy, textToVerify, focus, errorMessage));

                string elementText = Browser.Driver.FindElement(findBy).Text;
                Assert.AreEqual(elementText, textToVerify, true, ErrorMessage(findBy, focus, errorMessage));
            }

            /// <summary>
            /// Process this Verify by a Value comparison.
            /// </summary>
            /// <param name="findBy">HTML text to identify and find elements within a document.</param>
            /// <param name="expectedValue">Text to compare with the .value attribute of the Document Element found.</param>
            /// <param name="focus">Document container with controls to search for.</param>
            public static void Value(string findBy, string expectedValue, Focus focus) {
                Value(findBy, expectedValue, focus, "");
            }

            /// <summary>
            /// Process this Verify by a Value comparison.
            /// </summary>
            /// <param name="findBy">HTML text to identify and find elements within a document.</param>
            /// <param name="expectedValue">Text to compare with the .value attribute of the Document Element found.</param>
            /// <param name="focus">Document container with controls to search for.</param>
            /// <param name="errorMessage">Error message to be displayed if there is no match.</param>
            public static void Value(string findBy, string expectedValue, Focus focus, string errorMessage) {
                Value(GetFindBy(findBy), expectedValue, focus, errorMessage);
            }

            /// <summary>
            /// Process this Verify by a Value comparison.
            /// </summary>
            /// <param name="findBy">Selenium object that provides a mechanism to find elements within a document</param>
            /// <param name="expectedValue">Text to compare with the .value attribute of the Document Element found.</param>
            /// <param name="focus">Document container with controls to search for.</param>
            /// <param name="errorMessage">Error message to be displayed if there is no match.</param>
            public static void Value(By findBy, string expectedValue, Focus focus, string errorMessage) {

                EasyTestLogger.Log(string.Format("findBy = {0} expectedValue = {1} focus = {2} errorMessage = {3}", findBy, expectedValue, focus, errorMessage));

                Attribute(findBy, focus, "value", expectedValue, errorMessage);
            }

            /// <summary>
            /// Process this Verify by an Attribute comparison.
            /// </summary>
            /// <param name="findBy">HTML text to identify and find elements within a document.</param>
            /// <param name="focus">Document container with controls to search for.</param>
            /// <param name="attribute">Name of the attribute to check.</param>
            /// <param name="attributeExpectedValue">Expected value to check for.</param>
            public static void Attribute(string findBy, Focus focus, string attribute, string expectedAttributeValue) {
                Attribute(findBy, focus, attribute, expectedAttributeValue, "");
            }

            /// <summary>
            /// Process this Verify by an Attribute comparison.
            /// </summary>
            /// <param name="findBy">HTML text to identify and find elements within a document.</param>
            /// <param name="focus">Document container with controls to search for.</param>
            /// <param name="attribute">Name of the attribute to check.</param>
            /// <param name="attributeExpectedValue">Expected value to check for.</param>
            /// <param name="errorMessage">Error message to be displayed if there is no match.</param>
            public static void Attribute(string findBy, Focus focus, string attribute, string expectedAttributeValue, string errorMessage) {
                Attribute(GetFindBy(findBy), focus, attribute, expectedAttributeValue, errorMessage);
            }

            /// <summary>
            /// Process this Verify by an Attribute comparison.
            /// </summary>
            /// <param name="findBy">Selenium object that provides a mechanism to find elements within a document</param>
            /// <param name="focus">Document container with controls to search for.</param>
            /// <param name="attribute">Name of the attribute to check.</param>
            /// <param name="attributeExpectedValue">Expected value to check for.</param>
            /// <param name="errorMessage">Error message to be displayed if there is no match.</param>
            public static void Attribute(By findBy, Focus focus, string attribute, string expectedAttributeValue, string errorMessage) {

                EasyTestLogger.Log(string.Format("findBy = {0} focus = {1} attribute = {2} expectedAttributeValue = {3} errorMessage = {4}", findBy, focus, attribute, expectedAttributeValue, errorMessage));

                string elementText = Browser.Driver.FindElement(findBy).GetAttribute(attribute);
                Assert.AreEqual(expectedAttributeValue, elementText, ErrorMessage(findBy, focus, errorMessage));
            }

            /// <summary>
            /// Determine whether or not an element found is displayed (visible) or not.
            /// </summary>
            /// <param name="findBy">HTML text to identify and find elements within a document.</param>
            /// <param name="focus">Document container with controls to search for.</param>
            public static void IsDisplayed(string findBy) {
                IsDisplayed(findBy, null, "");
            }

            /// <summary>
            /// Determine whether or not an element found is displayed (visible) or not.
            /// </summary>
            /// <param name="findBy">HTML text to identify and find elements within a document.</param>
            /// <param name="focus">Document container with controls to search for.</param>
            /// <param name="errorMessage">Error message to be displayed if there is no match.</param>
            public static void IsDisplayed(string findBy, Focus focus, string errorMessage) {
                IsDisplayed(GetFindBy(findBy), focus, errorMessage);
            }

            /// <summary>
            /// Determine whether or not an element found is displayed (visible) or not.
            /// </summary>
            /// <param name="findBy">Selenium object that provides a mechanism to find elements within a document</param>
            /// <param name="focus">Document container with controls to search for.</param>
            /// <param name="errorMessage">Error message to be displayed if there is no match.</param>
            public static void IsDisplayed(By findBy, Focus focus, string errorMessage) {
                Assert.IsTrue(Action.IsDisplayed(findBy), ErrorMessage(findBy, focus, errorMessage));
            }
            /// <summary>
            /// Determine whether or not an element exist in the DOM.
            /// </summary>
            /// <param name="findBy">HTML text to identify and find elements within a document.</param>
            public static void Exists(string findBy)
            {
                Exists(findBy, null, "");
            }

            /// <summary>
            /// Determine whether or not an element exist in the DOM.
            /// </summary>
            /// <param name="findBy">HTML text to identify and find elements within a document.</param>
            /// <param name="focus">Document container with controls to search for.</param>
            /// <param name="errorMessage">Error message to be displayed if there is no match.</param>
            public static void Exists(string findBy, Focus focus, string errorMessage)
            {
                Exists(GetFindBy(findBy), focus, errorMessage);
            }

            /// <summary>
            /// Determine whether or not an element  exist in the DOM.
            /// </summary>
            /// <param name="findBy">Selenium object that provides a mechanism to find elements within a document</param>
            /// <param name="focus">Document container with controls to search for.</param>
            /// <param name="errorMessage">Error message to be displayed if there is no match.</param>
            public static void Exists(By findBy, Focus focus, string errorMessage)
            {
                Assert.IsTrue(Action.Exist(findBy,true), ErrorMessage(findBy, focus, errorMessage));
            }
            public static void NotExists(string findBy, Focus focus)
            {
                NotExists(findBy,focus,"");
            }
            public static void NotExists(string findBy, Focus focus, string errorMessage)
            {
                Assert.IsFalse(Action.Exist(findBy), ErrorMessage(GetFindBy(findBy), focus, errorMessage));
            }
            /// <summary>
            /// All error messages for current Verify operation.
            /// </summary>
            /// <param name="findBy">Selenium object that provides a mechanism to find elements within a document</param>
            /// <param name="focus">Document container with controls to search for.</param>
            /// <param name="errorMessage">Error message to be displayed if there is no match.</param>
            /// <returns>Complete error message after all error messages have been concatenated from the current operation.</returns>
            private static string ErrorMessage(By findBy, Focus focus, string errorMessage) {
                errorMessage = errorMessage + Environment.NewLine;
                if (focus is Frame) {
                    Frame frame = (Frame)focus;
                    errorMessage = "on ParentFocus: " + frame.ParentFocus.Name + " on Frame: " + frame.Name + " with Find By:" +
                                   findBy.ToString();
                }
                if (focus is Page) {
                    Page page = (Page)focus;
                    errorMessage = "on ParentFocus: " + page.Name + " with Find By:" + findBy.ToString();
                }
                return errorMessage = errorMessage;
            }
        }

        /// <summary>
        /// Process this Verify by a partial Text comparison.
        /// </summary>
        /// <param name="findBy">HTML text to identify and find elements within a document.</param>
        /// <param name="textToVerify">Text to search for in the .Text property of the Document Element found.</param>
        public static void VerifyContainsText(string findBy, string textToVerify) {
            VerifyContainsText(findBy, textToVerify);
        }

        /// <summary>
        /// Process this Verify by a partial Text comparison.
        /// </summary>
        /// <param name="findBy">HTML text to identify and find elements within a document.</param>
        /// <param name="textToVerify">Text to search for in the .Text property of the Document Element found.</param>
        /// <param name="errorMessage">Error message to be displayed if there is no match.</param>
        public static void VerifyContainsText(string findBy, string textToVerify, string errorMessage) {
            string elementText = Browser.Driver.FindElement(GetFindBy(findBy)).Text;
            Assert.IsTrue(elementText.Contains(textToVerify), errorMessage);
        }

        /// <summary>
        /// Process this Verify by a Text comparison.
        /// </summary>
        /// <param name="findBy">HTML text to identify and find elements within a document.</param>
        /// <param name="textToVerify">Text to search for in the .Text property of the Document Element found.</param>
        public static void VerifyText(string findBy, string textToVerify) {
            VerifyText(GetFindBy(findBy), textToVerify, "");
        }

        /// <summary>
        /// Process this Verify by a Text comparison.
        /// </summary>
        /// <param name="findBy">HTML text to identify and find elements within a document.</param>
        /// <param name="textToVerify">Text to search for in the .Text property of the Document Element found.</param>
        /// <param name="errorMessage">Error message to be displayed if there is no match.</param>
        public static void VerifyText(string findBy, string textToVerify, string errorMessage) {
            VerifyText(GetFindBy(findBy), textToVerify, errorMessage);
        }

        /// <summary>
        /// Process this Verify by a Text comparison.
        /// </summary>
        /// <param name="findBy">Selenium object that provides a mechanism to find elements within a document</param>
        /// <param name="textToVerify">Text to search for in the .Text property of the Document Element found.</param>
        /// <param name="errorMessage">Error message to be displayed if there is no match.</param>
        public static void VerifyText(By findBy, string textToVerify, string errorMessage) {
            string elementText = Browser.Driver.FindElement(findBy).Text;
            Assert.AreEqual(elementText, textToVerify, true, errorMessage);
        }
        /// <summary>
        /// Process this Verify by an comparing the value attribute of the HTML element.
        /// </summary>
        /// <param name="findBy">HTML text to identify and find elements within a document.</param>
        /// <param name="textToVerify">Name of the attribute to check.</param>
        public static void VerifyValue(string findBy, string textToVerify)
        {
            VerifyAttribute(findBy, "value", textToVerify);
        }
        /// <summary>
        /// Process this Verify by an comparing the value attribute of the HTML element.
        /// </summary>
        /// <param name="findBy">HTML text to identify and find elements within a document.</param>
        /// <param name="textToVerify">Name of the attribute to check.</param>
        /// <param name="errorMessage">Optional error message to pass on fail</param>
        public static void VerifyValue(string findBy, string textToVerify, string errorMessage)
        {
            VerifyAttribute(findBy,"value",textToVerify,errorMessage);
        }
        /// <summary>
        /// Process this Verify by an Attribute comparison.
        /// </summary>
        /// <param name="findBy">HTML text to identify and find elements within a document.</param>
        /// <param name="attribute">Name of the attribute to check.</param>
        /// <param name="textToCheck">Text to compare with the attribute of the Document Element found.</param>
        public static void VerifyAttribute(string findBy, string attribute, string textToCheck) {
            VerifyAttribute(GetFindBy(findBy), attribute, textToCheck,"");
        }

        /// <summary>
        /// Process this Verify by an Attribute comparison.
        /// </summary>
        /// <param name="findBy">HTML text to identify and find elements within a document.</param>
        /// <param name="attribute">Name of the attribute to check.</param>
        /// <param name="textToCheck">Text to compare with the attribute of the Document Element found.</param>
        /// <param name="errorMessage">Optional error message to pass on fail</param>
        public static void VerifyAttribute(string findBy, string attribute, string textToCheck,string errorMessage)
        {
            VerifyAttribute(GetFindBy(findBy), attribute, textToCheck, errorMessage);
        }

        /// <summary>
        /// Process this Verify by an Attribute comparison.
        /// </summary>
        /// <param name="findBy">Selenium object that provides a mechanism to find elements within a document</param>
        /// <param name="attribute">Name of the attribute to check.</param>
        /// <param name="textToCheck">Text to compare with the attribute of the Document Element found.</param>
        public static void VerifyAttribute(By findBy, string attribute, string textToCheck, string errorMessage) {
            string elementText = Browser.Driver.FindElement(findBy).GetAttribute(attribute);
            Assert.AreEqual(elementText, textToCheck,errorMessage);
        }

        /// <summary>
        /// Determine whether or not a Document Element exists.
        /// </summary>
        /// <param name="findBy">HTML text to identify and find elements within a document.</param>
        /// <returns>True/False whether or not the Document Element searched for exists.</returns>
        public static bool Exist(string findBy) {
            return Exist(GetFindBy(findBy),false);
        }
        public static bool Exist(string findBy, bool wait)
        {
            return Exist(GetFindBy(findBy), wait);
        }
        /// <summary>
        /// Determine whether or not a Document Element exists.
        /// </summary>
        /// <param name="findBy">Selenium object that provides a mechanism to find elements within a document</param>
        /// <returns>True/False whether or not the Document Element searched for exists.</returns>
        public static bool Exist(By findBy,bool wait) {
            try {
                if (!wait)
                {
                    Browser.Driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromMilliseconds(0));   
                }
                
                IWebElement element = Browser.Driver.FindElement(findBy);
                if (!wait)
                {
                    Browser.Driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromMilliseconds(0));
                }
                Browser.Driver.Manage().Timeouts().ImplicitlyWait(Browser.MaxWait);
                return true;
            } catch (Exception e) {
                return false;
            }
        }

        /// <summary>
        /// Determine whether or not an element found is displayed (visible) or not.
        /// </summary>
        /// <param name="findBy">HTML text to identify and find elements within a document.</param>
        /// <returns>True/False whether or not the Document Element searched for is displayed (visible).</returns>
        public static bool IsDisplayed(string findBy) {
            return IsDisplayed(Action.GetFindBy(findBy));
        }

        /// <summary>
        /// Determine whether or not an element found is displayed (visible) or not.
        /// </summary>
        /// <param name="findBy">Selenium object that provides a mechanism to find elements within a document</param>
        /// <returns>True/False whether or not the Document Element searched for is displayed (visible).</returns>
        private static bool IsDisplayed(By findBy) {
            try {
                //Set implicit wait to short time
                Browser.Driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromMilliseconds(0));
                //Check if element is visible, if it doesn't exist it will throw an exception.
                bool isVisible = Browser.Driver.FindElement(findBy).Displayed;
                Browser.Driver.Manage().Timeouts().ImplicitlyWait(Browser.MaxWait);
                return isVisible;
            } catch (Exception e) {
                //if element isn't on Focuses then return false
                return false;
            }
        }

        /// <summary>
        /// Timer to pause for the number of seconds passed after an element is found and is displayed.
        /// </summary>
        /// <param name="findBy">HTML text to identify and find elements within a document</param>
        /// <param name="seconds">Number of seconds to wait.</param>
        public static void WaitFor(string findBy, int seconds) {
            WaitFor(GetFindBy(findBy), seconds);
        }
        public static void WaitFor(string findBy)
        {
            WaitFor(findBy,20);
        }
        public static void WaitFor(By findBy)
        {
            WaitFor(findBy, 20);
        }
        /// <summary>
        /// Timer to pause for the number of seconds passed after an element is found and is displayed.
        /// </summary>
        /// <param name="findBy">Selenium object that provides a mechanism to find elements within a document</param>
        /// <param name="seconds">Number of seconds to wait.</param>
        public static void WaitFor(By findBy, int seconds) {
            for (int i = 0; i <= (seconds * 10); i++) {
                if (IsDisplayed(findBy)&IsEnabled(findBy))
                {
                    return;
                }
                System.Threading.Thread.Sleep(100);
            }
        }
        public static bool IsEnabled(By findBy)
        {
            try
            {
                return Browser.Driver.FindElement(findBy).Enabled;
            }
            catch (Exception e)
            {
                return false;
            }
            
        }
        
    }

    /// <summary>
    /// 
    /// </summary>
    public enum CheckOption { RemoveSpaces, Trim, RemoveCase }

}
